/*

Miranda IM: the free IM client for Microsoft* Windows*

Copyright 2000-2007 Miranda ICQ/IM project, 
all portions of this codebase are copyrighted to the people 
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or ( at your option ) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "commonheaders.h"
#include "ExtraServices.h"
#include "m_contacts.h"

namespace NServices 
{
	namespace Gender 
	{

		static HANDLE nhExtraIconF	= INVALID_HANDLE_VALUE;
		static HANDLE nhExtraIconM	= INVALID_HANDLE_VALUE;

		BYTE Get( HANDLE hContact, LPCSTR szProto )
		{
			DBVARIANT dbv;

			if( DB::Setting::GetAsIsEx( hContact, USERINFO, szProto, SET_CONTACT_GENDER, &dbv ) == 0 )
			{
				// gender must be byte and either M or F
				if( dbv.type == DBVT_BYTE && ( dbv.bVal == 'M' || dbv.bVal == 'F' ) )
				{
					return dbv.bVal;	
				}
				DB::Variant::Free( &dbv );
			}
			return 0;
		}

		/**
		 * This function gets the gender of the contact from the database.
		 *
		 * @param		hContact	- handle to contact to read email from
		 *
		 * @retval	F	- contact is female
		 * @retval	M	- contact is male
		 * @retval	0	- contact does not provide its gender
		 **/
		BYTE Get( HANDLE hContact )
		{
			return Get( hContact, DB::Contact::Proto( hContact ) );
		}

		/***********************************************************************************************************
		 * Event Handler functions
		 ***********************************************************************************************************/

		static INT OnCListRebuildIcons( WPARAM wParam, LPARAM lParam )
		{
			nhExtraIconF = ( HANDLE )CallService( MS_CLIST_EXTRA_ADD_ICON, ( WPARAM )NIcoLib::GetIcon( ICO_COMMON_FEMALE ), 0 );
			nhExtraIconM = ( HANDLE )CallService( MS_CLIST_EXTRA_ADD_ICON, ( WPARAM )NIcoLib::GetIcon( ICO_COMMON_MALE ), 0 );
			return 0;
		}

		/**
		 * Notification handler for clist extra icons to be applied for a contact.
		 *
		 * @param wParam	- handle to the contact whose extra icon is to apply
		 * @param	lParam	- not used
		 **/
		static INT OnCListApplyIcons( WPARAM wParam, LPARAM lParam )
		{
			IconExtraColumn iec;

			iec.ColumnType = ColumnType( DB::Setting::GetByte( SET_CLIST_EXTRAICON_GENDER, DEFVAL_CLIST_EXTRAICON_GENDER ) );
			if( iec.ColumnType ) 
			{
				iec.cbSize = sizeof( IconExtraColumn );
				switch( Get( ( HANDLE )wParam ) ) 
				{
					case 'M': 
						{
							iec.hImage = nhExtraIconM; 
							break;
						}
					case 'F': 
						{
							iec.hImage = nhExtraIconF; 
							break;
						}
					default:
						{
							iec.hImage = INVALID_HANDLE_VALUE;
						}
				}
				CallService( MS_CLIST_EXTRA_SET_ICON, wParam, ( LPARAM )&iec );
			}
			return 0;
		}

		/**
		 * Notification handler for changed contact settings
		 *
		 * @param	wParam	-	( HANDLE )hContact
		 * @param	lParam	-	( DBCONTACTWRITESETTING* )pdbcws
		 **/
		static INT OnContactSettingChanged( WPARAM wParam, LPARAM lParam )
		{
			if( wParam )
			{
				DBCONTACTWRITESETTING* pdbcws = ( DBCONTACTWRITESETTING* )lParam;
				
				if( pdbcws && pdbcws->szSetting )
				{
					/*if( !_strcmp( pdbcws->szSetting, SET_CONTACT_GENDER ) ) 
					{
						OnCListApplyIcons( wParam, 0 );
					}
					*/
				}
			}
			return 0;
		}

		/***********************************************************************************************************
		 * public Module Interface functions
		 ***********************************************************************************************************/

		/**
		 * Force all icons to be reloaded.
		 *
		 * @param	wParam	- handle to the contact whose extra icon is to apply
		 * @param lParam	- not used
		 **/
		VOID ApplyCListIcons()
		{
			HANDLE hContact;

			//walk through all the contacts stored in the DB
			for( hContact = DB::Contact::FindFirst();	hContact != NULL;	hContact = DB::Contact::FindNext( hContact ) )
			{
				OnCListApplyIcons( ( WPARAM ) hContact, 0 );
			}
		}

		/**
		 * Enable or disable the replacement of clist extra icons.
		 *
		 * @param	bEnable		- determines whether icons are enabled or not
		 * @param bUpdateDB	- if true the database setting is updated, too.
		 **/
		VOID EnableExtraIcons( BYTE bColumn, BOOLEAN bUpdateDB ) 
		{
			if( myGlobals.HaveCListExtraIcons )
			{
				static HANDLE	hChangedHook			= NULL;
				static HANDLE	hApplyIconHook		= NULL;
				static HANDLE	hRebuildIconsHook = NULL;

				if( bUpdateDB )
				{
					DB::Setting::WriteByte( SET_CLIST_EXTRAICON_GENDER, bColumn );
				}

				if( bColumn ) 
				{
					// hook events
					if( hChangedHook == NULL ) 
					{
						hChangedHook = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged );
					}
					if( hApplyIconHook == NULL ) 
					{
						hApplyIconHook = HookEvent( ME_CLIST_EXTRA_IMAGE_APPLY, OnCListApplyIcons );
					}
					if( hRebuildIconsHook == NULL ) 
					{
						hRebuildIconsHook = HookEvent( ME_CLIST_EXTRA_LIST_REBUILD, OnCListRebuildIcons );
						OnCListRebuildIcons( 0, 0 );
					}
				}
				else 
				{
					UnhookEvent( hChangedHook ); 
					hChangedHook = NULL;
					
					UnhookEvent( hApplyIconHook ); 
					hApplyIconHook = NULL;
					
					UnhookEvent( hRebuildIconsHook ); 
					hRebuildIconsHook = NULL;
				}
				ApplyCListIcons();
			}
		}

		/**
		 * This function initially loads the module uppon startup.
		 **/
		VOID LoadModule()
		{
			EnableExtraIcons( DB::Setting::GetByte( SET_CLIST_EXTRAICON_GENDER, DEFVAL_CLIST_EXTRAICON_GENDER ), FALSE );
		}

	} /* namespace Gender */

} /* namespace NServices */
